Game đuổi chó sa mạc lập trình bằng ngôn ngữ c#
19.379 lượt xem;
1 /**
2 * @fileOverview
3 * Defines UnityObject2
4 */
5
6
7 //TODO: No need to polute the global space, just transfer this control to a 'static' variable insite unityObject!
8 /**
9 * @namespace
10 */
11 //var unity = unity || {};
12 // We store all unityObject instances in a global scope, needed for IE firstFrameCallback and other internal tasks.
13 //unity.instances = [];
14 //unity.instanceNumber = 0;
15
16 /**
17 * Object expected by the Java Installer. We can move those to UnityObject2 if we update the java Installer.
18 */
19 var unityObject = {
20 /**
21 * Callback used bt the Java installer to notify the Install Complete.
22 * @private
23 * @param {String} id
24 * @param {bool} success
25 * @param {String} errormessage
26 */
27 javaInstallDone : function (id, success, errormessage) {
28
29 var instanceId = parseInt(id.substring(id.lastIndexOf('_') + 1), 10);
30
31 if (!isNaN(instanceId)) {
32
33 // javaInstallDoneCallback must not be called directly because it deadlocks google chrome
34 setTimeout(function () {
35
36 UnityObject2.instances[instanceId].javaInstallDoneCallback(id, success, errormessage);
37 }, 10);
38 }
39 }
40 };
41
42
43 /**
44 * @class
45 * @constructor
46 */
47 var UnityObject2 = function (config) {
48
49 /** @private */
50 var logHistory = [],
51 win = window,
52 doc = document,
53 nav = navigator,
54 instanceNumber = null,
55 //domLoaded = false,
56 //domLoadEvents = [],
57 embeddedObjects = [], //Could be removed?
58 //listeners = [],
59 //styleSheet = null,
60 //styleSheetMedia = null,
61 //autoHideShow = true,
62 //fullSizeMissing = true,
63 useSSL = (document.location.protocol == 'https:'), //This will turn off enableUnityAnalytics, since enableUnityAnalytics don't have a https version.
64 baseDomain = useSSL ? "https://ssl-webplayer.unity3d.com/" : "http://webplayer.unity3d.com/",
65 triedJavaCookie = "_unity_triedjava",
66 triedJavaInstall = _getCookie(triedJavaCookie),
67 triedClickOnceCookie = "_unity_triedclickonce",
68 triedClickOnce = _getCookie(triedClickOnceCookie),
69 progressCallback = false,
70 applets = [],
71 //addedClickOnce = false,
72 googleAnalyticsLoaded = false,
73 googleAnalyticsCallback = null,
74 latestStatus = null,
75 lastType = null,
76 //beginCallback = [],
77 //preCallback = [],
78 imagesToWaitFor = [],
79 //referrer = null,
80 pluginStatus = null,
81 pluginStatusHistory = [],
82 installProcessStarted = false, //not used anymore?
83 kInstalled = "installed",
84 kMissing = "missing",
85 kBroken = "broken",
86 kUnsupported = "unsupported",
87 kReady = "ready", //not used anymore?
88 kStart = "start",
89 kError = "error",
90 kFirst = "first",
91 //kStandard = "standard",
92 kJava = "java",
93 kClickOnce = "clickonce", //not used anymore?
94 wasMissing = false, //identifies if this is a install attempt, or if the plugin was already installed
95 unityObject = null, //The <embed> or <object> for the webplayer. This can be used for webPlayer communication.
96 //kApplet = "_applet",
97 //kBanner = "_banner",
98
99 cfg = {
100 pluginName : "Unity Player",
101 pluginMimeType : "application/vnd.unity",
102 baseDownloadUrl : baseDomain + "download_webplayer-3.x/",
103 fullInstall : false,
104 autoInstall : false,
105 enableJava : true,
106 enableJVMPreloading : false,
107 enableClickOnce : true,
108 enableUnityAnalytics : false,
109 enableGoogleAnalytics : true,
110 params : {},
111 attributes : {},
112 referrer : null,
113 debugLevel : 0,
114 pluginVersionChecker : {
115 container : jQuery("body")[0],
116 hide : true,
117 id : "version-checker"
118 }
119 };
120
121 // Merge in the given configuration and override defaults.
122 cfg = jQuery.extend(true, cfg, config);
123
124 if (cfg.referrer === "") {
125 cfg.referrer = null;
126 }
127 //enableUnityAnalytics does not support SSL yet.
128 if (useSSL) {
129 cfg.enableUnityAnalytics = false;
130 }
131
132 /**
133 * Get cookie value
134 * @private
135 * @param {String} name The param name
136 * @return string or false if non-existing.
137 */
138 function _getCookie(name) {
139
140 var e = new RegExp(escape(name) + "=([^;]+)");
141
142 if (e.test(doc.cookie + ";")) {
143
144 e.exec(doc.cookie + ";");
145 return RegExp.$1;
146 }
147
148 return false;
149 }
150
151 /**
152 * Sets session cookie
153 * @private
154 */
155 function _setSessionCookie(name, value) {
156
157 document.cookie = escape(name) + "=" + escape(value) + "; path=/";
158 }
159
160 /**
161 * Converts unity version to number (used for version comparison)
162 * @private
163 */
164 function _getNumericUnityVersion(version) {
165
166 var result = 0,
167 major,
168 minor,
169 fix,
170 type,
171 release;
172
173 if (version) {
174
175 var m = version.toLowerCase().match(/^(\d+)(?:\.(\d+)(?:\.(\d+)([dabfr])?(\d+)?)?)?$/);
176
177 if (m && m[1]) {
178
179 major = m[1];
180 minor = m[2] ? m[2] : 0;
181 fix = m[3] ? m[3] : 0;
182 type = m[4] ? m[4] : 'r';
183 release = m[5] ? m[5] : 0;
184 result |= ((major / 10) % 10) << 28;
185 result |= (major % 10) << 24;
186 result |= (minor % 10) << 20;
187 result |= (fix % 10) << 16;
188 result |= {d: 2 << 12, a: 4 << 12, b: 6 << 12, f: 8 << 12, r: 8 << 12}[type];
189 result |= ((release / 100) % 10) << 8;
190 result |= ((release / 10) % 10) << 4;
191 result |= (release % 10);
192 }
193 }
194
195 return result;
196 }
197
198 /**
199 * Gets plugin and unity versions (non-ie)
200 * @private
201 */
202 function _getPluginVersion(callback, versions) {
203
204 var b = cfg.pluginVersionChecker.container;
205 var ue = doc.createElement("object");
206 var i = 0;
207
208 if (b && ue) {
209 ue.setAttribute("type", cfg.pluginMimeType);
210 ue.setAttribute("id", cfg.pluginVersionChecker.id);
211 if (cfg.pluginVersionChecker.hide)
212 ue.style.visibility = "hidden";
213 b.appendChild(ue);
214
215 (function () {
216 if (typeof ue.GetPluginVersion === "undefined") {
217 setTimeout(arguments.callee, 100);
218 } else {
219
220 var v = {};
221
222 if (versions) {
223
224 for (i = 0; i < versions.length; ++i) {
225
226 v[versions[i]] = ue.GetUnityVersion(versions[i]);
227 }
228 }
229
230 v.plugin = ue.GetPluginVersion();
231 b.removeChild(ue);
232 callback(v);
233 }
234 })();
235
236 } else {
237
238 callback(null);
239 }
240 }
241
242 /**
243 * Retrieves windows installer name
244 * @private
245 */
246 function _getWinInstall() {
247 var url = "";
248
249 if (ua.x64) {
250 url = cfg.fullInstall ? "UnityWebPlayerFull64.exe" : "UnityWebPlayer64.exe";
251 } else {
252 url = cfg.fullInstall ? "UnityWebPlayerFull.exe" : "UnityWebPlayer.exe";
253 }
254
255 if (cfg.referrer !== null) {
256
257 url += "?referrer=" + cfg.referrer;
258 }
259 return url;
260 }
261
262 /**
263 * Retrieves mac plugin package name
264 * @private
265 */
266 function _getOSXInstall() {
267
268 var url = "UnityPlayer.plugin.zip";
269
270 if (cfg.referrer != null) {
271
272 url += "?referrer=" + cfg.referrer;
273 }
274 return url;
275 }
276
277 /**
278 * retrieves installer name
279 * @private
280 */
281 function _getInstaller() {
282
283 return cfg.baseDownloadUrl + (ua.win ? _getWinInstall() : _getOSXInstall() );
284 }
285
286 /**
287 * sets plugin status
288 * @private
289 */
290 function _setPluginStatus(status, type, data, url) {
291
292 if (status === kMissing) {
293 wasMissing = true;
294 }
295
296 // debug('setPluginStatus() status:', status, 'type:', type, 'data:', data, 'url:', url);
297
298 // only report to analytics the first time a status occurs.
299 if ( jQuery.inArray(status, pluginStatusHistory) === -1 ) {
300
301 //Only send analytics for plugins installs. Do not send if plugin is already installed.
302 if (wasMissing) {
303 _an.send(status, type, data, url);
304 }
305 pluginStatusHistory.push(status);
306 }
307
308 pluginStatus = status;
309 }
310
311
312 /**
313 * Contains browser and platform properties
314 * @private
315 */
316 var ua = function () {
317
318 var a = nav.userAgent, p = nav.platform;
319 var chrome = /chrome/i.test(a);
320
321 //starting from IE 11, IE is using a different UserAgent.
322 var ie = false;
323 if (/msie/i.test(a)){
324 ie = parseFloat(a.replace(/^.*msie ([0-9]+(\.[0-9]+)?).*$/i, "$1"));
325 } else if (/Trident/i.test(a)) {
326 ie = parseFloat(a.replace(/^.*rv:([0-9]+(\.[0-9]+)?).*$/i, "$1"));
327 }
328 var ua = {
329 w3 : typeof doc.getElementById != "undefined" && typeof doc.getElementsByTagName != "undefined" && typeof doc.createElement != "undefined",
330 win : p ? /win/i.test(p) : /win/i.test(a),
331 mac : p ? /mac/i.test(p) : /mac/i.test(a),
332 ie : ie,
333 ff : /firefox/i.test(a),
334 op : /opera/i.test(a),
335 ch : chrome,
336 ch_v : /chrome/i.test(a) ? parseFloat(a.replace(/^.*chrome\/(\d+(\.\d+)?).*$/i, "$1")) : false,
337 sf : /safari/i.test(a) && !chrome,
338 wk : /webkit/i.test(a) ? parseFloat(a.replace(/^.*webkit\/(\d+(\.\d+)?).*$/i, "$1")) : false,
339 x64 : /win64/i.test(a) && /x64/i.test(a),
340 moz : /mozilla/i.test(a) ? parseFloat(a.replace(/^.*mozilla\/([0-9]+(\.[0-9]+)?).*$/i, "$1")) : 0,
341 mobile: /ipad/i.test(p) || /iphone/i.test(p) || /ipod/i.test(p) || /android/i.test(a) || /windows phone/i.test(a)
342 };
343
344 ua.clientBrand = ua.ch ? 'ch' : ua.ff ? 'ff' : ua.sf ? 'sf' : ua.ie ? 'ie' : ua.op ? 'op' : '??';
345 ua.clientPlatform = ua.win ? 'win' : ua.mac ? 'mac' : '???';
346
347 // get base url
348 var s = doc.getElementsByTagName("script");
349
350 for (var i = 0; i < s.length; ++i) {
351
352 var m = s[i].src.match(/^(.*)3\.0\/uo\/UnityObject2\.js$/i);
353
354 if (m) {
355
356 cfg.baseDownloadUrl = m[1];
357 break;
358 }
359 }
360
361 /**
362 * compares two versions
363 * @private
364 */
365 function _compareVersions(v1, v2) {
366
367 for (var i = 0; i < Math.max(v1.length, v2.length); ++i) {
368
369 var n1 = (i < v1.length) && v1[i] ? new Number(v1[i]) : 0;
370 var n2 = (i < v2.length) && v2[i] ? new Number(v2[i]) : 0;
371 if (n1 < n2) return -1;
372 if (n1 > n2) return 1;
373 }
374
375 return 0;
376 };
377
378 /**
379 * detect java
380 */
381 ua.java = function () {
382
383 if (nav.javaEnabled()) {
384
385 var wj = (ua.win && ua.ff);
386 var mj = false;//(ua.mac && (ua.ff || ua.ch || ua.sf));
387
388 if (wj || mj) {
389
390 if (typeof nav.mimeTypes != "undefined") {
391
392 var rv = wj ? [1, 6, 0, 12] : [1, 4, 2, 0];
393
394 for (var i = 0; i < nav.mimeTypes.length; ++i) {
395
396 if (nav.mimeTypes[i].enabledPlugin) {
397
398 var m = nav.mimeTypes[i].type.match(/^application\/x-java-applet;(?:jpi-)?version=(\d+)(?:\.(\d+)(?:\.(\d+)(?:_(\d+))?)?)?$/);
399
400 if (m != null) {
401
402 if (_compareVersions(rv, m.slice(1)) <= 0) {
403
404 return true;
405 }
406 }
407 }
408 }
409 }
410 } else if (ua.win && ua.ie) {
411
412 if (typeof ActiveXObject != "undefined") {
413
414 /**
415 * ActiveX Test
416 */
417 function _axTest(v) {
418
419 try {
420
421 return new ActiveXObject("JavaWebStart.isInstalled." + v + ".0") != null;
422 }
423 catch (ex) {
424
425 return false;
426 }
427 }
428
429 /**
430 * ActiveX Test 2
431 */
432 function _axTest2(v) {
433
434 try {
435
436 return new ActiveXObject("JavaPlugin.160_" + v) != null;
437 } catch (ex) {
438
439 return false;
440 }
441 }
442
443 if (_axTest("1.7.0")) {
444
445 return true;
446 }
447
448 if (ua.ie >= 8) {
449
450 if (_axTest("1.6.0")) {
451
452 // make sure it's 1.6.0.12 or newer. increment 50 to a larger value if 1.6.0.50 is released
453 for (var i = 12; i <= 50; ++i) {
454
455 if (_axTest2(i)) {
456
457 if (ua.ie == 9 && ua.moz == 5 && i < 24) {
458 // when IE9 is not in compatibility mode require at least
459 // Java 1.6.0.24: http://support.microsoft.com/kb/2506617
460 continue;
461 } else {
462
463 return true;
464 }
465 }
466 }
467
468 return false;
469 }
470 } else {
471
472 return _axTest("1.6.0") || _axTest("1.5.0") || _axTest("1.4.2");
473 }
474 }
475 }
476 }
477
478 return false;
479 }();
480
481 // detect clickonce
482 ua.co = function () {
483
484 if (ua.win && ua.ie) {
485 var av = a.match(/(\.NET CLR [0-9.]+)|(\.NET[0-9.]+)/g);
486 if (av != null) {
487 var rv = [3, 5, 0];
488 for (var i = 0; i < av.length; ++i) {
489 var versionNumbers = av[i].match(/[0-9.]{2,}/g)[0].split(".");
490 if (_compareVersions(rv, versionNumbers) <= 0) {
491 return true;
492 }
493 }
494 }
495 }
496 return false;
497
498 }();
499
500 return ua;
501 }();
502
503
504 /**
505 * analytics
506 * @private
507 */
508 var _an = function () {
509 var uid = function () {
510
511 var now = new Date();
512 var utc = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDay(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds());
513 return utc.toString(16) + _getRandomInt().toString(16);
514 }();
515 var seq = 0;
516 var _ugaq = window["_gaq"] = ( window["_gaq"] || [] );
517
518 _setUpAnalytics();
519
520 /**
521 * generates random integer number
522 * @private
523 */
524 function _getRandomInt() {
525
526 return Math.floor(Math.random() * 2147483647);
527 }
528
529 /**
530 * Checks if there is a need to load analytics, by checking the existance of a _gaq object
531 */
532 function _setUpAnalytics() {
533
534 var gaUrl = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
535 var ss = doc.getElementsByTagName("script");
536 var googleAnalyticsLoaded = false;
537 for (var i = 0; i < ss.length; ++i) {
538
539 if (ss[i].src && ss[i].src.toLowerCase() == gaUrl.toLowerCase()) {
540
541 googleAnalyticsLoaded = true;
542 break;
543 }
544 }
545
546 if (!googleAnalyticsLoaded) {
547 var ga = doc.createElement("script");
548 ga.type = "text/javascript";
549 ga.async = true;
550 ga.src = gaUrl;
551 var s = document.getElementsByTagName("script")[0];
552 s.parentNode.insertBefore(ga, s);
553 }
554
555 var gaAccount = (cfg.debugLevel === 0) ? 'UA-16068464-16' : 'UA-16068464-17';
556
557 _ugaq.push(["unity._setDomainName", "none"]);
558 _ugaq.push(["unity._setAllowLinker", true]);
559 _ugaq.push(["unity._setReferrerOverride", ' '+this.location.toString()]);
560
561 _ugaq.push(["unity._setAccount", gaAccount]);
562 // $(GoogleRevisionPlaceholder)
563 }
564
565 /**
566 * sends analytics data to unity
567 * @private
568 */
569 function _sendUnityAnalytics(event, type, data, callback) {
570
571 if (!cfg.enableUnityAnalytics) {
572
573 if (callback) {
574
575 callback();
576 }
577
578 return;
579 }
580
581 var url = "http://unityanalyticscapture.appspot.com/event?u=" + encodeURIComponent(uid) + "&s=" + encodeURIComponent(seq) + "&e=" + encodeURIComponent(event);
582 // $(UnityRevisionPlaceholder)
583
584 if (cfg.referrer !== null) {
585
586 url += "?r=" + cfg.referrer;
587 }
588
589 if (type) {
590
591 url += "&t=" + encodeURIComponent(type);
592 }
593
594 if (data) {
595
596 url += "&d=" + encodeURIComponent(data);
597 }
598
599 var img = new Image();
600
601 if (callback) {
602
603 img.onload = img.onerror = callback;
604 }
605
606 img.src = url;
607 }
608
609 /**
610 * sends analytics data to google
611 * @private
612 */
613 function _sendGoogleAnalytics(event, type, data, callback) {
614
615 if (!cfg.enableGoogleAnalytics) {
616
617 if (callback) {
618
619 callback();
620 }
621
622 return;
623 }
624
625 var url = "/webplayer/install/" + event;
626 var join = "?";
627
628 if (type) {
629
630 url += join + "t=" + encodeURIComponent(type);
631 join = "&";
632 }
633
634 if (data) {
635
636 url += join + "d=" + encodeURIComponent(data);
637 join = "&";
638 }
639
640 if (callback) {
641
642 _ugaq.push(function () {
643 setTimeout(callback,1000);
644 //this.googleAnalyticsCallback = callback;
645 });
646 }
647
648 //try to shorten the URL to fit into customVariable
649 //it will try to replace the early directories to ..
650 var gameUrl = cfg.src;
651 if (gameUrl.length > 40) {
652 gameUrl = gameUrl.replace("http://","");
653 var paths = gameUrl.split("/");
654
655 var gameUrlFirst = paths.shift();
656 var gameUrlLast = paths.pop();
657 gameUrl = gameUrlFirst + "/../"+ gameUrlLast;
658
659 while(gameUrl.length < 40 && paths.length > 0) {
660 var nextpath = paths.pop();
661 if(gameUrl.length + nextpath.length + 5 < 40) {
662 gameUrlLast = nextpath + "/" + gameUrlLast;
663 } else {
664 gameUrlLast = "../" + gameUrlLast;
665 }
666 gameUrl = gameUrlFirst + "/../"+ gameUrlLast;
667 }
668 }
669 _ugaq.push(['unity._setCustomVar',
670 2, // This custom var is set to slot #1. Required parameter.
671 'GameURL', // The name acts as a kind of category for the user activity. Required parameter.
672 gameUrl, // This value of the custom variable. Required parameter.
673 3 // Sets the scope to page-level. Optional parameter.
674 ]);
675 _ugaq.push(['unity._setCustomVar',
676 1, // This custom var is set to slot #1. Required parameter.
677 'UnityObjectVersion', // The name acts as a kind of category for the user activity. Required parameter.
678 "2", // This value of the custom variable. Required parameter.
679 3 // Sets the scope to page-level. Optional parameter.
680 ]);
681 if (type) {
682 _ugaq.push(['unity._setCustomVar',
683 3, // This custom var is set to slot #1. Required parameter.
684 'installMethod', // The name acts as a kind of category for the user activity. Required parameter.
685 type, // This value of the custom variable. Required parameter.
686 3 // Sets the scope to page-level. Optional parameter.
687 ]);
688 }
689
690 _ugaq.push(["unity._trackPageview", url]);
691 }
692
693 return {
694 /**
695 * sends analytics data. optionally opens url once data has been sent
696 * @public
697 */
698 send : function (event, type, data, url) {
699
700 if (cfg.enableUnityAnalytics || cfg.enableGoogleAnalytics) {
701
702 debug('Analytics SEND', event, type, data, url);
703 }
704
705 ++seq;
706 var count = 2;
707
708 var callback = function () {
709
710 if (0 == --count) {
711
712 googleAnalyticsCallback = null;
713 window.location = url;
714 }
715 }
716
717 if (data === null || data === undefined) {
718 data = "";
719 }
720
721 _sendUnityAnalytics(event, type, data, url ? callback : null);
722 _sendGoogleAnalytics(event, type, data, url ? callback : null);
723 }
724 };
725 }();
726
727
728
729
730
731 /* Java Install - BEGIN */
732
733 /**
734 * @private
735 */
736 function _createObjectElement(attributes, params, elementToReplace) {
737
738 var i,
739 at,
740 pt,
741 ue,
742 pe;
743
744 if (ua.win && ua.ie) {
745
746 at = "";
747
748 for (i in attributes) {
749
750 at += ' ' + i + '="' + attributes[i] + '"';
751 }
752
753 pt = "";
754
755 for (i in params) {
756
757 pt += '<param name="' + i + '" value="' + params[i] + '" />';
758 }
759
760 elementToReplace.outerHTML = '<object' + at + '>' + pt + '</object>';
761
762 } else {
763
764 ue = doc.createElement("object");
765
766 for (i in attributes) {
767
768 ue.setAttribute(i, attributes[i]);
769 }
770
771 for (i in params) {
772
773 pe = doc.createElement("param");
774 pe.name = i;
775 pe.value = params[i];
776 ue.appendChild(pe);
777 }
778
779 elementToReplace.parentNode.replaceChild(ue, elementToReplace);
780 }
781 }
782
783 /**
784 * @private
785 */
786 function _checkImage(img) {
787
788 // img element not in the DOM yet
789 if (typeof img == "undefined") {
790
791 return false;
792 }
793
794 if (!img.complete) {
795
796 return false;
797 }
798
799 // some browsers always return true in img.complete, for those
800 // we can check naturalWidth
801 if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) {
802
803 return false;
804 }
805
806 // no other way of checking, assuming it is ok
807 return true;
808 }
809
810 /**
811 * @private
812 */
813 function _preloadJVMWhenReady(id) {
814
815 var needToWait = false;
816
817 for (var i = 0; i < imagesToWaitFor.length; i++) {
818 if (!imagesToWaitFor[i]) {
819 continue;
820 }
821 var img = doc.images[imagesToWaitFor[i]];
822 if (!_checkImage(img)) {
823 needToWait = true;
824 }
825 else {
826 imagesToWaitFor[i] = null;
827 }
828 }
829 if (needToWait) {
830 // check again in 100ms
831 setTimeout(arguments.callee, 100);
832 }
833 else {
834 // preload after a small delay, to make sure
835 // the images have actually rendered
836 setTimeout(function () {
837 _preloadJVM(id);
838 }, 100);
839 }
840 }
841
842
843 /**
844 * preloads the JVM and the Java Plug-in
845 * @private
846 */
847 function _preloadJVM(id) {
848
849 var re = doc.getElementById(id);
850
851 if (!re) {
852
853 re = doc.createElement("div");
854 var lastBodyElem = doc.body.lastChild;
855 doc.body.insertBefore(re, lastBodyElem.nextSibling);
856 }
857
858 var codebase = cfg.baseDownloadUrl + "3.0/jws/";
859
860 var a = {
861 id : id,
862 type : "application/x-java-applet",
863 code : "JVMPreloader",
864 width : 1,
865 height : 1,
866 name : "JVM Preloader"
867 };
868
869 var p = {
870 context : id,
871 codebase : codebase,
872 classloader_cache : false,
873 scriptable : true,
874 mayscript : true
875 };
876
877 _createObjectElement(a, p, re);
878 jQuery('#' + id).show();
879 //setVisibility(id, true);
880 }
881
882 /**
883 * launches java installer
884 * @private
885 */
886 function _doJavaInstall(id) {
887
888 triedJavaInstall = true;
889 _setSessionCookie(triedJavaCookie, triedJavaInstall);
890 var re = doc.getElementById(id);
891 var appletID = id + "_applet_" + instanceNumber;
892
893 applets[appletID] = {
894 attributes : cfg.attributes,
895 params : cfg.params,
896 callback : cfg.callback,
897 broken : cfg.broken
898 };
899
900 var applet = applets[appletID];
901
902 var a = {
903 id : appletID,
904 type : "application/x-java-applet",
905 archive : cfg.baseDownloadUrl + "3.0/jws/UnityWebPlayer.jar",
906 code : "UnityWebPlayer",
907 width : 1,
908 height : 1,
909 name : "Unity Web Player"
910 };
911
912 if (ua.win && ua.ff) {
913
914 a["style"] = "visibility: hidden;";
915 }
916
917 var p = {
918 context : appletID,
919 jnlp_href : cfg.baseDownloadUrl + "3.0/jws/UnityWebPlayer.jnlp",
920 classloader_cache : false,
921 installer : _getInstaller(),
922 image : baseDomain + "installation/unitylogo.png",
923 centerimage : true,
924 boxborder : false,
925 scriptable : true,
926 mayscript : true
927 };
928
929 for (var i in applet.params) {
930
931 if (i == "src") {
932
933 continue;
934 }
935
936 if (applet.params[i] != Object.prototype[i]) {
937
938 p[i] = applet.params[i];
939
940 if (i.toLowerCase() == "logoimage") {
941
942 p["image"] = applet.params[i];
943 }
944 else if (i.toLowerCase() == "backgroundcolor") {
945
946 p["boxbgcolor"] = "#" + applet.params[i];
947 }
948 else if (i.toLowerCase() == "bordercolor") {
949
950 // there's no way to specify border color
951 p["boxborder"] = true;
952 }
953 else if (i.toLowerCase() == "textcolor") {
954
955 p["boxfgcolor"] = "#" + applet.params[i];
956 }
957 }
958 }
959
960 // Create a dummy div element in the unityPlayer div
961 // so that it can be replaced with the 1x1 px applet.
962 // The applet will be resized when it has fully loaded,
963 // see appletStarted().
964 var divToBeReplacedWithApplet = doc.createElement("div");
965 re.appendChild(divToBeReplacedWithApplet);
966 _createObjectElement(a, p, divToBeReplacedWithApplet);
967 jQuery('#' + id).show();
968 //setVisibility(appletID, true);
969 }
970
971 /**
972 * @private
973 */
974 function _jvmPreloaded(id) {
975
976 // timeout prevents crash on ie
977 setTimeout(function () {
978
979 var re = doc.getElementById(id);
980
981 if (re) {
982 re.parentNode.removeChild(re);
983 }
984 }, 0);
985 }
986
987 /**
988 * @private
989 */
990 function _appletStarted(id) {
991 // set the size of the applet to the one from cloned attributes
992 var applet = applets[id],
993 appletElement = doc.getElementById(id),
994 childNode;
995
996 // the applet might have already finished by now
997 if (!appletElement) {
998
999 return;
1000 }
1001
1002 appletElement.width = applet.attributes["width"] || 600;
1003 appletElement.height = applet.attributes["height"] || 450;
1004
1005 // remove all the siblings of the applet
1006 var parentNode = appletElement.parentNode;
1007 var childNodeList = parentNode.childNodes;
1008
1009 for (var i = 0; i < childNodeList.length; i++) {
1010
1011 childNode = childNodeList[i];
1012 // Compare the child node with our applet element only if
1013 // it has the same type. Doing the comparison in other cases just
1014 // jumps out of the loop.
1015 if (childNode.nodeType == 1 && childNode != appletElement) {
1016
1017 parentNode.removeChild(childNode);
1018 }
1019 }
1020 }
1021
1022
1023 // java installation callback
1024 function _javaInstallDoneCallback(id, success, errormessage) {
1025
1026 debug('_javaInstallDoneCallback', id, success, errormessage);
1027 //console.log('javaInstallDoneCallback', id, success, errormessage);
1028
1029 if (!success) {
1030
1031 //var applet = applets[id];
1032 _setPluginStatus(kError, kJava, errormessage);
1033 //createMissingUnity(id, applet.attributes, applet.params, applet.callback, applet.broken, kJava, errormessage);
1034 }
1035 }
1036
1037 /* Java Install - END */
1038
1039
1040 /**
1041 * @private
1042 */
1043 function log() {
1044
1045 logHistory.push(arguments);
1046
1047 if ( cfg.debugLevel > 0 && window.console && window.console.log ) {
1048
1049 console.log(Array.prototype.slice.call(arguments));
1050 //console.log.apply(console, Array.prototype.slice.call(arguments));
1051 }
1052 }
1053
1054 /**
1055 * @private
1056 */
1057 function debug() {
1058
1059 logHistory.push(arguments);
1060
1061 if ( cfg.debugLevel > 1 && window.console && window.console.log ) {
1062
1063 console.log(Array.prototype.slice.call(arguments));
1064 //console.log.apply(console, Array.prototype.slice.call(arguments));
1065 }
1066 }
1067
1068 /**
1069 * appends px to the value if it's a plain number
1070 * @private
1071 */
1072 function _appendPX(value) {
1073
1074 if (/^[-+]?[0-9]+$/.test(value)) {
1075 value += "px";
1076 }
1077 return value;
1078 }
1079
1080 /**
1081 * detects unity web player.
1082 * @public
1083 * callback - accepts two parameters.
1084 * first one contains "installed", "missing", "broken" or "unsupported" value.
1085 * second one returns requested unity versions. plugin version is included as well.
1086 * versions - array of unity versions to detect.
1087 */
1088 function _detectUnityInternal (callback, versions) {
1089
1090 // console.debug('detectUnity this:', this);
1091 var self = this;
1092
1093 var status = kMissing;
1094 var data;
1095 nav.plugins.refresh();
1096
1097 if (ua.clientBrand === "??" || ua.clientPlatform === "???" || ua.mobile ) {
1098 status = kUnsupported;
1099 } else if (ua.op && ua.mac) { // Opera on MAC is unsupported
1100
1101 status = kUnsupported;
1102 data = "OPERA-MAC";
1103 } else if (
1104 typeof nav.plugins != "undefined"
1105 && nav.plugins[cfg.pluginName]
1106 && typeof nav.mimeTypes != "undefined"
1107 && nav.mimeTypes[cfg.pluginMimeType]
1108 && nav.mimeTypes[cfg.pluginMimeType].enabledPlugin
1109 ) {
1110
1111 status = kInstalled;
1112
1113 // make sure web player is compatible with 64-bit safari
1114 if (ua.sf && /Mac OS X 10_6/.test(nav.appVersion)) {
1115
1116 _getPluginVersion(function (version) {
1117
1118 if (!version || !version.plugin) {
1119
1120 status = kBroken;
1121 data = "OSX10.6-SFx64";
1122 }
1123
1124 callback(status, lastType, data, version);
1125 }, versions);
1126
1127 return;
1128 } else if (ua.mac && ua.ch) { // older versions have issues on chrome
1129
1130 _getPluginVersion(function (version) {
1131
1132 if (version && (_getNumericUnityVersion(version.plugin) <= _getNumericUnityVersion("2.6.1f3"))) {
1133 status = kBroken;
1134 data = "OSX-CH-U<=2.6.1f3";
1135 }
1136
1137 callback(status, lastType, data, version);
1138 }, versions);
1139
1140 return;
1141 } else if (versions) {
1142
1143 _getPluginVersion(function (version) {
1144 callback(status, lastType, data, version);
1145 }, versions);
1146 return;
1147 }
1148 } else if (ua.ie) {
1149 var activeXSupported = false;
1150 try {
1151 if (ActiveXObject.prototype != null) {
1152 activeXSupported = true;
1153 }
1154 } catch(e) {}
1155
1156 if (!activeXSupported) {
1157 status = kUnsupported;
1158 data = "ActiveXFailed";
1159 } else {
1160 status = kMissing;
1161 try {
1162 var uo = new ActiveXObject("UnityWebPlayer.UnityWebPlayer.1");
1163 var pv = uo.GetPluginVersion();
1164
1165 if (versions) {
1166 var v = {};
1167 for (var i = 0; i < versions.length; ++i) {
1168 v[versions[i]] = uo.GetUnityVersion(versions[i]);
1169 }
1170 v.plugin = pv;
1171 }
1172
1173 status = kInstalled;
1174 // 2.5.0 auto update has issues on vista and later
1175 if (pv == "2.5.0f5") {
1176 var m = /Windows NT \d+\.\d+/.exec(nav.userAgent);
1177 if (m && m.length > 0) {
1178 var wv = parseFloat(m[0].split(' ')[2]);
1179 if (wv >= 6) {
1180 status = kBroken;
1181 data = "WIN-U2.5.0f5";
1182 }
1183 }
1184 }
1185 } catch(e) {}
1186 }
1187 }
1188 callback(status, lastType, data, v);
1189 }
1190
1191 /**
1192 * Detects unity web player. But doesn't modify the current UnityObject instance, and doesn't send analytics.
1193 * @public
1194 * callback - accepts two parameters.
1195 * first one contains "installed", "missing", "broken" or "unsupported" value.
1196 * second one returns requested unity versions. plugin version is included as well.
1197 * versions - array of unity versions to detect.
1198 */
1199 function _detectUnityNoAnalytics (callback, versions) {
1200 _detectUnityInternal(function(status, lastType, data, v){
1201 callback(status, v);
1202 }, versions);
1203 }
1204
1205 /**
1206 * Detects unity web player. Also modify the current UnityObject instance, and sends analytics.
1207 * @public
1208 * callback - accepts two parameters.
1209 * first one contains "installed", "missing", "broken" or "unsupported" value.
1210 * second one returns requested unity versions. plugin version is included as well.
1211 * versions - array of unity versions to detect.
1212 */
1213 function _detectUnityWithAnalytics (callback, versions) {
1214 _detectUnityInternal(function(status, lastType, data, v){
1215 _setPluginStatus(status, lastType, data);
1216 callback(status, v);
1217 }, versions);
1218 }
1219
1220
1221 var publicAPI = /** @lends UnityObject2.prototype */ {
1222
1223 /**
1224 * Get Debug Level (0=Disabled)
1225 * @public
1226 * @return {Number} Debug Level
1227 */
1228 getLogHistory: function () {
1229
1230 return logHistory; // JSON.stringify()
1231 },
1232
1233
1234 /**
1235 * Get configuration object
1236 * @public
1237 * @return {Object} cfg
1238 */
1239 getConfig: function () {
1240
1241 return cfg; // JSON.stringify()
1242 },
1243
1244
1245 /**
1246 * @public
1247 * @return {Object} detailed info about OS and Browser.
1248 */
1249 getPlatformInfo: function () {
1250
1251 return ua;
1252 },
1253
1254
1255 /**
1256 * Initialize plugin config and proceed with attempting to start the webplayer.
1257 * @public
1258 */
1259 initPlugin: function (targetEl, src) {
1260
1261 cfg.targetEl = targetEl;
1262 cfg.src = src;
1263
1264 debug('ua:', ua);
1265 //console.debug('initPlugin this:', this);
1266 //_detectUnityWithAnalytics(this.handlePluginStatus);
1267 var self = this;
1268 _detectUnityWithAnalytics(function(status, v){
1269 self.handlePluginStatus(status, v);
1270 });
1271 },
1272
1273
1274 /**
1275 * detects unity web player.
1276 * @public
1277 * callback - accepts two parameters.
1278 * first one contains "installed", "missing", "broken" or "unsupported" value.
1279 * second one returns requested unity versions. plugin version is included as well.
1280 * versions - optional array of unity versions to detect.
1281 */
1282 detectUnity: function (callback, versions) {
1283 var self = this;
1284 _detectUnityNoAnalytics(function(status, v){
1285 callback.call(self, status, v);
1286 }, versions);
1287 },
1288
1289
1290
1291 /**
1292 * @public
1293 * @return {Object} with info about Unity WebPlayer plugin status (not installed, loading, running etc..)
1294 */
1295 handlePluginStatus: function (status, versions) {
1296
1297 // Store targetEl in the closure, to be able to get it back if setTimeout calls again.
1298 var targetEl = cfg.targetEl;
1299
1300 var $targetEl = jQuery(targetEl);
1301
1302 switch(status) {
1303
1304 case kInstalled:
1305
1306 // @todo add support for alternate custom handlers.
1307 this.notifyProgress($targetEl);
1308 this.embedPlugin($targetEl, cfg.callback);
1309 break;
1310
1311 case kMissing:
1312
1313 this.notifyProgress($targetEl);
1314 //this.installPlugin($targetEl);
1315
1316 var self = this;
1317 var delayTime = (cfg.debugLevel === 0) ? 1000 : 8000;
1318
1319 // Do a delay and re-check for plugin
1320 setTimeout(function () {
1321
1322 cfg.targetEl = targetEl;
1323 self.detectUnity(self.handlePluginStatus);
1324 }, delayTime);
1325
1326 break;
1327
1328 case kBroken:
1329 // Browser needs to restart after install
1330 this.notifyProgress($targetEl);
1331 break;
1332
1333 case kUnsupported:
1334
1335 this.notifyProgress($targetEl);
1336 break;
1337 }
1338
1339 },
1340
1341 /**
1342 * @public
1343 * @return {Object} with detailed plugin info, version number and other info that can be retrieved from the plugin.
1344 */
1345 /*getPluginInfo: function () {
1346
1347 },*/
1348
1349 /**
1350 * @public
1351 */
1352 getPluginURL: function () {
1353
1354 var url = "http://unity3d.com/webplayer/";
1355
1356 if (ua.win) {
1357
1358 url = cfg.baseDownloadUrl + _getWinInstall();
1359
1360 } else if (nav.platform == "MacIntel") {
1361
1362 url = cfg.baseDownloadUrl + (cfg.fullInstall ? "webplayer-i386.dmg" : "webplayer-mini.dmg");
1363
1364 if (cfg.referrer !== null) {
1365
1366 url += "?referrer=" + cfg.referrer;
1367 }
1368
1369 } else if (nav.platform == "MacPPC") {
1370
1371 url = cfg.baseDownloadUrl + (cfg.fullInstall ? "webplayer-ppc.dmg" : "webplayer-mini.dmg");
1372
1373 if (cfg.referrer !== null) {
1374
1375 url += "?referrer=" + cfg.referrer;
1376 }
1377 }
1378
1379 return url;
1380 },
1381
1382 /**
1383 * @public
1384 */
1385 getClickOnceURL: function () {
1386
1387 return cfg.baseDownloadUrl + "3.0/co/UnityWebPlayer.application?installer=" + encodeURIComponent(cfg.baseDownloadUrl + _getWinInstall());
1388 },
1389
1390 /**
1391 * Embed the plugin into the DOM.
1392 * @public
1393 */
1394 embedPlugin: function (targetEl, callback) {
1395
1396 targetEl = jQuery(targetEl).empty();
1397
1398 var src = cfg.src; //targetEl.data('src'),
1399 var width = cfg.width || "100%"; //TODO: extract those hardcoded values
1400 var height = cfg.height || "100%";
1401 var self = this;
1402
1403 if (ua.win && ua.ie) {
1404 // ie, dom and object element do not mix & match
1405
1406 var at = "";
1407
1408 for (var i in cfg.attributes) {
1409 if (cfg.attributes[i] != Object.prototype[i]) {
1410 if (i.toLowerCase() == "styleclass") {
1411 at += ' class="' + cfg.attributes[i] + '"';
1412 }
1413 else if (i.toLowerCase() != "classid") {
1414 at += ' ' + i + '="' + cfg.attributes[i] + '"';
1415 }
1416 }
1417 }
1418
1419 var pt = "";
1420
1421 // we manually add SRC here, because its now defined on the target element.
1422 pt += '<param name="src" value="' + src + '" />';
1423 pt += '<param name="firstFrameCallback" value="UnityObject2.instances[' + instanceNumber + '].firstFrameCallback();" />';
1424
1425 for (var i in cfg.params) {
1426
1427 if (cfg.params[i] != Object.prototype[i]) {
1428
1429 if (i.toLowerCase() != "classid") {
1430
1431 pt += '<param name="' + i + '" value="' + cfg.params[i] + '" />';
1432 }
1433 }
1434 }
1435
1436 //var tmpHtml = '<div id="' + targetEl.attr('id') + '" style="width: ' + _appendPX(width) + '; height: ' + _appendPX(height) + ';"><object classid="clsid:444785F1-DE89-4295-863A-D46C3A781394" style="display: block; width: 100%; height: 100%;"' + at + '>' + pt + '</object></div>';
1437 var tmpHtml = '<object classid="clsid:444785F1-DE89-4295-863A-D46C3A781394" style="display: block; width: ' + _appendPX(width) + '; height: ' + _appendPX(height) + ';"' + at + '>' + pt + '</object>';
1438 var $object = jQuery(tmpHtml);
1439 targetEl.append( $object );
1440 embeddedObjects.push( targetEl.attr('id') );
1441 unityObject = $object[0];
1442
1443 } else {
1444
1445 // Create and append embed element into DOM.
1446 var $embed = jQuery('<embed/>')
1447 .attr({
1448 src: src,
1449 type: cfg.pluginMimeType,
1450 width: width,
1451 height: height,
1452 firstFrameCallback: 'UnityObject2.instances[' + instanceNumber + '].firstFrameCallback();'
1453 })
1454 .attr(cfg.attributes)
1455 .attr(cfg.params)
1456 .css({
1457 display: 'block',
1458 width: _appendPX(width),
1459 height: _appendPX(height)
1460 })
1461 .appendTo( targetEl );
1462 unityObject = $embed[0];
1463 }
1464
1465 //Auto focus the new object/embed, so players dont have to click it before using it.
1466 //setTimeout is here to workaround a chrome bug.
1467 //we should not invoke focus on safari on mac. it causes some Input bugs.
1468 if (!ua.sf || !ua.mac) {
1469 setTimeout(function() {
1470 unityObject.focus();
1471 }, 100);
1472 }
1473
1474 if (callback) {
1475
1476 callback();
1477 }
1478 },
1479
1480 /**
1481 * Determine which installation method to use on the current platform, and return an array with their identifiers (i.e. 'ClickOnceIE', 'JavaInstall', 'Manual')
1482 * Take into account which previous methods might have been attempted (and failed) and skip to next best method.
1483 * @public
1484 * @return {String}
1485 */
1486 getBestInstallMethod: function () {
1487
1488 // Always fall back to good old manual (download) install.
1489 var method = 'Manual';
1490
1491 //We only have manual install for 64bit plugin so far.
1492 if (ua.x64)
1493 return method;
1494
1495 // Is Java available and not yet attempted?
1496 if (cfg.enableJava && ua.java && triedJavaInstall === false) {
1497
1498 method = 'JavaInstall';
1499 }
1500 // Is ClickOnce available and not yet attempted?
1501 else if (cfg.enableClickOnce && ua.co && triedClickOnce === false) {
1502
1503 method = 'ClickOnceIE';
1504 }
1505
1506 return method;
1507 },
1508
1509 /**
1510 * Tries to install the plugin using the specified method.
1511 * If no method is passed, it will try to use this.getBestInstallMethod()
1512 * @public
1513 * @param {String} method The desired install method
1514 */
1515 installPlugin: function(method) {
1516 if (method == null || method == undefined) {
1517 method = this.getBestInstallMethod();
1518 }
1519
1520 var urlToOpen = null;
1521 switch(method) {
1522
1523 case "JavaInstall":
1524 this.doJavaInstall(cfg.targetEl.id);
1525 break;
1526 case "ClickOnceIE":
1527 triedClickOnce = true;
1528 _setSessionCookie(triedClickOnceCookie, triedClickOnce);
1529 var $iframe = jQuery("<iframe src='" + this.getClickOnceURL() + "' style='display:none;' />");
1530 jQuery(cfg.targetEl).append($iframe);
1531 break;
1532 default:
1533 case "Manual":
1534 //doc.location = this.getPluginURL();
1535 //urlToOpen = this.getPluginURL();
1536 var $iframe = jQuery("<iframe src='" + this.getPluginURL() + "' style='display:none;' />");
1537 jQuery(cfg.targetEl).append($iframe);
1538 break;
1539 }
1540
1541 lastType = method;
1542 _an.send(kStart, method, null, null);
1543
1544 },
1545
1546 /**
1547 * Trigger event using jQuery(document).trigger()
1548 * @public
1549 */
1550 //TODO: verify its use.
1551 trigger: function (event, params) {
1552
1553 if (params) {
1554
1555 debug('trigger("' + event + '")', params);
1556
1557 } else {
1558
1559 debug('trigger("' + event + '")');
1560 }
1561
1562 jQuery(document).trigger(event, params);
1563 },
1564
1565 /**
1566 * Notify observers about onProgress event
1567 * @public
1568 */
1569 notifyProgress: function (targetEl) {
1570
1571 //debug('*** notifyProgress ***')
1572
1573 if (typeof progressCallback !== "undefined" && typeof progressCallback === "function") {
1574
1575 var payload = {
1576
1577 ua: ua,
1578 pluginStatus: pluginStatus,
1579 bestMethod: null,
1580 lastType: lastType,
1581 targetEl: cfg.targetEl,
1582 unityObj: this
1583 };
1584
1585 if (pluginStatus === kMissing) {
1586
1587 payload.bestMethod = this.getBestInstallMethod();
1588 }
1589
1590 if (latestStatus !== pluginStatus) { //Execute only on state change
1591 latestStatus = pluginStatus;
1592
1593 progressCallback(payload);
1594 }
1595 }
1596 },
1597
1598 /**
1599 * Subscribe to onProgress notification
1600 * @public
1601 */
1602 observeProgress: function (callback) {
1603
1604 progressCallback = callback;
1605 },
1606
1607
1608 /**
1609 * Callback made by the WebPlayer plugin when the first frame is rendered.
1610 * @public
1611 */
1612 firstFrameCallback : function () {
1613
1614 debug('*** firstFrameCallback (' + instanceNumber + ') ***');
1615 pluginStatus = kFirst;
1616 this.notifyProgress();
1617
1618 /*
1619 // What?
1620 if (status == kFirst) {
1621 if (pluginStatus == null) {
1622 return;
1623 }
1624 }
1625 */
1626
1627 //Webplayer was already installed.
1628 //Should only log firstframes if it happened after a install.
1629 if (wasMissing === true) {
1630 _an.send(pluginStatus, lastType);
1631 }
1632
1633 //setRunStatus(kFirst, lastType);
1634 },
1635
1636 /**
1637 * Get a string from a session cookie or SessionStorage
1638 * @public
1639 * @return {String}
1640 */
1641 /*getSessionString: function (key) {
1642
1643 },*/
1644
1645 /**
1646 * Set a string via a session cookie or SessionStorage
1647 * @public
1648 */
1649 /* setSessionString: function (key, value) {
1650
1651 },*/
1652
1653 /**
1654 * Get a string from a persistent cookie
1655 * @public
1656 * @return {String}
1657 */
1658 /*getCookie: function (key) {
1659
1660 },*/
1661
1662 /**
1663 * Set a string to a persistent cookie
1664 * @public
1665 */
1666 /*setCookie: function (key, value, expiryDate) {
1667
1668 },*/
1669
1670 /**
1671 * Exposed private function
1672 * @public
1673 */
1674 setPluginStatus: function (status, type, data, url) {
1675
1676 _setPluginStatus(status, type, data, url);
1677 },
1678
1679 /**
1680 * Exposed private function
1681 * @public
1682 */
1683 doJavaInstall : function (id) {
1684
1685 _doJavaInstall(id);
1686 },
1687
1688 /**
1689 * Exposed private function
1690 * @public
1691 */
1692 jvmPreloaded : function (id) {
1693
1694 _jvmPreloaded(id);
1695 },
1696
1697 /**
1698 * Exposed private function
1699 * @public
1700 */
1701 appletStarted : function (id) {
1702
1703 _appletStarted(id);
1704 },
1705
1706 /**
1707 * Exposed private function
1708 * @public
1709 */
1710 javaInstallDoneCallback : function (id, success, errormessage) {
1711
1712 _javaInstallDoneCallback(id, success, errormessage);
1713 },
1714
1715 getUnity: function() {
1716 return unityObject;
1717 }
1718 }
1719
1720 // Internal store of each instance.
1721 instanceNumber = UnityObject2.instances.length;
1722 UnityObject2.instances.push(publicAPI);
1723
1724 return publicAPI;
1725
1726 };
1727
1728 /**
1729 * @static
1730 **/
1731 UnityObject2.instances = [];
2 * @fileOverview
3 * Defines UnityObject2
4 */
5
6
7 //TODO: No need to polute the global space, just transfer this control to a 'static' variable insite unityObject!
8 /**
9 * @namespace
10 */
11 //var unity = unity || {};
12 // We store all unityObject instances in a global scope, needed for IE firstFrameCallback and other internal tasks.
13 //unity.instances = [];
14 //unity.instanceNumber = 0;
15
16 /**
17 * Object expected by the Java Installer. We can move those to UnityObject2 if we update the java Installer.
18 */
19 var unityObject = {
20 /**
21 * Callback used bt the Java installer to notify the Install Complete.
22 * @private
23 * @param {String} id
24 * @param {bool} success
25 * @param {String} errormessage
26 */
27 javaInstallDone : function (id, success, errormessage) {
28
29 var instanceId = parseInt(id.substring(id.lastIndexOf('_') + 1), 10);
30
31 if (!isNaN(instanceId)) {
32
33 // javaInstallDoneCallback must not be called directly because it deadlocks google chrome
34 setTimeout(function () {
35
36 UnityObject2.instances[instanceId].javaInstallDoneCallback(id, success, errormessage);
37 }, 10);
38 }
39 }
40 };
41
42
43 /**
44 * @class
45 * @constructor
46 */
47 var UnityObject2 = function (config) {
48
49 /** @private */
50 var logHistory = [],
51 win = window,
52 doc = document,
53 nav = navigator,
54 instanceNumber = null,
55 //domLoaded = false,
56 //domLoadEvents = [],
57 embeddedObjects = [], //Could be removed?
58 //listeners = [],
59 //styleSheet = null,
60 //styleSheetMedia = null,
61 //autoHideShow = true,
62 //fullSizeMissing = true,
63 useSSL = (document.location.protocol == 'https:'), //This will turn off enableUnityAnalytics, since enableUnityAnalytics don't have a https version.
64 baseDomain = useSSL ? "https://ssl-webplayer.unity3d.com/" : "http://webplayer.unity3d.com/",
65 triedJavaCookie = "_unity_triedjava",
66 triedJavaInstall = _getCookie(triedJavaCookie),
67 triedClickOnceCookie = "_unity_triedclickonce",
68 triedClickOnce = _getCookie(triedClickOnceCookie),
69 progressCallback = false,
70 applets = [],
71 //addedClickOnce = false,
72 googleAnalyticsLoaded = false,
73 googleAnalyticsCallback = null,
74 latestStatus = null,
75 lastType = null,
76 //beginCallback = [],
77 //preCallback = [],
78 imagesToWaitFor = [],
79 //referrer = null,
80 pluginStatus = null,
81 pluginStatusHistory = [],
82 installProcessStarted = false, //not used anymore?
83 kInstalled = "installed",
84 kMissing = "missing",
85 kBroken = "broken",
86 kUnsupported = "unsupported",
87 kReady = "ready", //not used anymore?
88 kStart = "start",
89 kError = "error",
90 kFirst = "first",
91 //kStandard = "standard",
92 kJava = "java",
93 kClickOnce = "clickonce", //not used anymore?
94 wasMissing = false, //identifies if this is a install attempt, or if the plugin was already installed
95 unityObject = null, //The <embed> or <object> for the webplayer. This can be used for webPlayer communication.
96 //kApplet = "_applet",
97 //kBanner = "_banner",
98
99 cfg = {
100 pluginName : "Unity Player",
101 pluginMimeType : "application/vnd.unity",
102 baseDownloadUrl : baseDomain + "download_webplayer-3.x/",
103 fullInstall : false,
104 autoInstall : false,
105 enableJava : true,
106 enableJVMPreloading : false,
107 enableClickOnce : true,
108 enableUnityAnalytics : false,
109 enableGoogleAnalytics : true,
110 params : {},
111 attributes : {},
112 referrer : null,
113 debugLevel : 0,
114 pluginVersionChecker : {
115 container : jQuery("body")[0],
116 hide : true,
117 id : "version-checker"
118 }
119 };
120
121 // Merge in the given configuration and override defaults.
122 cfg = jQuery.extend(true, cfg, config);
123
124 if (cfg.referrer === "") {
125 cfg.referrer = null;
126 }
127 //enableUnityAnalytics does not support SSL yet.
128 if (useSSL) {
129 cfg.enableUnityAnalytics = false;
130 }
131
132 /**
133 * Get cookie value
134 * @private
135 * @param {String} name The param name
136 * @return string or false if non-existing.
137 */
138 function _getCookie(name) {
139
140 var e = new RegExp(escape(name) + "=([^;]+)");
141
142 if (e.test(doc.cookie + ";")) {
143
144 e.exec(doc.cookie + ";");
145 return RegExp.$1;
146 }
147
148 return false;
149 }
150
151 /**
152 * Sets session cookie
153 * @private
154 */
155 function _setSessionCookie(name, value) {
156
157 document.cookie = escape(name) + "=" + escape(value) + "; path=/";
158 }
159
160 /**
161 * Converts unity version to number (used for version comparison)
162 * @private
163 */
164 function _getNumericUnityVersion(version) {
165
166 var result = 0,
167 major,
168 minor,
169 fix,
170 type,
171 release;
172
173 if (version) {
174
175 var m = version.toLowerCase().match(/^(\d+)(?:\.(\d+)(?:\.(\d+)([dabfr])?(\d+)?)?)?$/);
176
177 if (m && m[1]) {
178
179 major = m[1];
180 minor = m[2] ? m[2] : 0;
181 fix = m[3] ? m[3] : 0;
182 type = m[4] ? m[4] : 'r';
183 release = m[5] ? m[5] : 0;
184 result |= ((major / 10) % 10) << 28;
185 result |= (major % 10) << 24;
186 result |= (minor % 10) << 20;
187 result |= (fix % 10) << 16;
188 result |= {d: 2 << 12, a: 4 << 12, b: 6 << 12, f: 8 << 12, r: 8 << 12}[type];
189 result |= ((release / 100) % 10) << 8;
190 result |= ((release / 10) % 10) << 4;
191 result |= (release % 10);
192 }
193 }
194
195 return result;
196 }
197
198 /**
199 * Gets plugin and unity versions (non-ie)
200 * @private
201 */
202 function _getPluginVersion(callback, versions) {
203
204 var b = cfg.pluginVersionChecker.container;
205 var ue = doc.createElement("object");
206 var i = 0;
207
208 if (b && ue) {
209 ue.setAttribute("type", cfg.pluginMimeType);
210 ue.setAttribute("id", cfg.pluginVersionChecker.id);
211 if (cfg.pluginVersionChecker.hide)
212 ue.style.visibility = "hidden";
213 b.appendChild(ue);
214
215 (function () {
216 if (typeof ue.GetPluginVersion === "undefined") {
217 setTimeout(arguments.callee, 100);
218 } else {
219
220 var v = {};
221
222 if (versions) {
223
224 for (i = 0; i < versions.length; ++i) {
225
226 v[versions[i]] = ue.GetUnityVersion(versions[i]);
227 }
228 }
229
230 v.plugin = ue.GetPluginVersion();
231 b.removeChild(ue);
232 callback(v);
233 }
234 })();
235
236 } else {
237
238 callback(null);
239 }
240 }
241
242 /**
243 * Retrieves windows installer name
244 * @private
245 */
246 function _getWinInstall() {
247 var url = "";
248
249 if (ua.x64) {
250 url = cfg.fullInstall ? "UnityWebPlayerFull64.exe" : "UnityWebPlayer64.exe";
251 } else {
252 url = cfg.fullInstall ? "UnityWebPlayerFull.exe" : "UnityWebPlayer.exe";
253 }
254
255 if (cfg.referrer !== null) {
256
257 url += "?referrer=" + cfg.referrer;
258 }
259 return url;
260 }
261
262 /**
263 * Retrieves mac plugin package name
264 * @private
265 */
266 function _getOSXInstall() {
267
268 var url = "UnityPlayer.plugin.zip";
269
270 if (cfg.referrer != null) {
271
272 url += "?referrer=" + cfg.referrer;
273 }
274 return url;
275 }
276
277 /**
278 * retrieves installer name
279 * @private
280 */
281 function _getInstaller() {
282
283 return cfg.baseDownloadUrl + (ua.win ? _getWinInstall() : _getOSXInstall() );
284 }
285
286 /**
287 * sets plugin status
288 * @private
289 */
290 function _setPluginStatus(status, type, data, url) {
291
292 if (status === kMissing) {
293 wasMissing = true;
294 }
295
296 // debug('setPluginStatus() status:', status, 'type:', type, 'data:', data, 'url:', url);
297
298 // only report to analytics the first time a status occurs.
299 if ( jQuery.inArray(status, pluginStatusHistory) === -1 ) {
300
301 //Only send analytics for plugins installs. Do not send if plugin is already installed.
302 if (wasMissing) {
303 _an.send(status, type, data, url);
304 }
305 pluginStatusHistory.push(status);
306 }
307
308 pluginStatus = status;
309 }
310
311
312 /**
313 * Contains browser and platform properties
314 * @private
315 */
316 var ua = function () {
317
318 var a = nav.userAgent, p = nav.platform;
319 var chrome = /chrome/i.test(a);
320
321 //starting from IE 11, IE is using a different UserAgent.
322 var ie = false;
323 if (/msie/i.test(a)){
324 ie = parseFloat(a.replace(/^.*msie ([0-9]+(\.[0-9]+)?).*$/i, "$1"));
325 } else if (/Trident/i.test(a)) {
326 ie = parseFloat(a.replace(/^.*rv:([0-9]+(\.[0-9]+)?).*$/i, "$1"));
327 }
328 var ua = {
329 w3 : typeof doc.getElementById != "undefined" && typeof doc.getElementsByTagName != "undefined" && typeof doc.createElement != "undefined",
330 win : p ? /win/i.test(p) : /win/i.test(a),
331 mac : p ? /mac/i.test(p) : /mac/i.test(a),
332 ie : ie,
333 ff : /firefox/i.test(a),
334 op : /opera/i.test(a),
335 ch : chrome,
336 ch_v : /chrome/i.test(a) ? parseFloat(a.replace(/^.*chrome\/(\d+(\.\d+)?).*$/i, "$1")) : false,
337 sf : /safari/i.test(a) && !chrome,
338 wk : /webkit/i.test(a) ? parseFloat(a.replace(/^.*webkit\/(\d+(\.\d+)?).*$/i, "$1")) : false,
339 x64 : /win64/i.test(a) && /x64/i.test(a),
340 moz : /mozilla/i.test(a) ? parseFloat(a.replace(/^.*mozilla\/([0-9]+(\.[0-9]+)?).*$/i, "$1")) : 0,
341 mobile: /ipad/i.test(p) || /iphone/i.test(p) || /ipod/i.test(p) || /android/i.test(a) || /windows phone/i.test(a)
342 };
343
344 ua.clientBrand = ua.ch ? 'ch' : ua.ff ? 'ff' : ua.sf ? 'sf' : ua.ie ? 'ie' : ua.op ? 'op' : '??';
345 ua.clientPlatform = ua.win ? 'win' : ua.mac ? 'mac' : '???';
346
347 // get base url
348 var s = doc.getElementsByTagName("script");
349
350 for (var i = 0; i < s.length; ++i) {
351
352 var m = s[i].src.match(/^(.*)3\.0\/uo\/UnityObject2\.js$/i);
353
354 if (m) {
355
356 cfg.baseDownloadUrl = m[1];
357 break;
358 }
359 }
360
361 /**
362 * compares two versions
363 * @private
364 */
365 function _compareVersions(v1, v2) {
366
367 for (var i = 0; i < Math.max(v1.length, v2.length); ++i) {
368
369 var n1 = (i < v1.length) && v1[i] ? new Number(v1[i]) : 0;
370 var n2 = (i < v2.length) && v2[i] ? new Number(v2[i]) : 0;
371 if (n1 < n2) return -1;
372 if (n1 > n2) return 1;
373 }
374
375 return 0;
376 };
377
378 /**
379 * detect java
380 */
381 ua.java = function () {
382
383 if (nav.javaEnabled()) {
384
385 var wj = (ua.win && ua.ff);
386 var mj = false;//(ua.mac && (ua.ff || ua.ch || ua.sf));
387
388 if (wj || mj) {
389
390 if (typeof nav.mimeTypes != "undefined") {
391
392 var rv = wj ? [1, 6, 0, 12] : [1, 4, 2, 0];
393
394 for (var i = 0; i < nav.mimeTypes.length; ++i) {
395
396 if (nav.mimeTypes[i].enabledPlugin) {
397
398 var m = nav.mimeTypes[i].type.match(/^application\/x-java-applet;(?:jpi-)?version=(\d+)(?:\.(\d+)(?:\.(\d+)(?:_(\d+))?)?)?$/);
399
400 if (m != null) {
401
402 if (_compareVersions(rv, m.slice(1)) <= 0) {
403
404 return true;
405 }
406 }
407 }
408 }
409 }
410 } else if (ua.win && ua.ie) {
411
412 if (typeof ActiveXObject != "undefined") {
413
414 /**
415 * ActiveX Test
416 */
417 function _axTest(v) {
418
419 try {
420
421 return new ActiveXObject("JavaWebStart.isInstalled." + v + ".0") != null;
422 }
423 catch (ex) {
424
425 return false;
426 }
427 }
428
429 /**
430 * ActiveX Test 2
431 */
432 function _axTest2(v) {
433
434 try {
435
436 return new ActiveXObject("JavaPlugin.160_" + v) != null;
437 } catch (ex) {
438
439 return false;
440 }
441 }
442
443 if (_axTest("1.7.0")) {
444
445 return true;
446 }
447
448 if (ua.ie >= 8) {
449
450 if (_axTest("1.6.0")) {
451
452 // make sure it's 1.6.0.12 or newer. increment 50 to a larger value if 1.6.0.50 is released
453 for (var i = 12; i <= 50; ++i) {
454
455 if (_axTest2(i)) {
456
457 if (ua.ie == 9 && ua.moz == 5 && i < 24) {
458 // when IE9 is not in compatibility mode require at least
459 // Java 1.6.0.24: http://support.microsoft.com/kb/2506617
460 continue;
461 } else {
462
463 return true;
464 }
465 }
466 }
467
468 return false;
469 }
470 } else {
471
472 return _axTest("1.6.0") || _axTest("1.5.0") || _axTest("1.4.2");
473 }
474 }
475 }
476 }
477
478 return false;
479 }();
480
481 // detect clickonce
482 ua.co = function () {
483
484 if (ua.win && ua.ie) {
485 var av = a.match(/(\.NET CLR [0-9.]+)|(\.NET[0-9.]+)/g);
486 if (av != null) {
487 var rv = [3, 5, 0];
488 for (var i = 0; i < av.length; ++i) {
489 var versionNumbers = av[i].match(/[0-9.]{2,}/g)[0].split(".");
490 if (_compareVersions(rv, versionNumbers) <= 0) {
491 return true;
492 }
493 }
494 }
495 }
496 return false;
497
498 }();
499
500 return ua;
501 }();
502
503
504 /**
505 * analytics
506 * @private
507 */
508 var _an = function () {
509 var uid = function () {
510
511 var now = new Date();
512 var utc = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDay(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds());
513 return utc.toString(16) + _getRandomInt().toString(16);
514 }();
515 var seq = 0;
516 var _ugaq = window["_gaq"] = ( window["_gaq"] || [] );
517
518 _setUpAnalytics();
519
520 /**
521 * generates random integer number
522 * @private
523 */
524 function _getRandomInt() {
525
526 return Math.floor(Math.random() * 2147483647);
527 }
528
529 /**
530 * Checks if there is a need to load analytics, by checking the existance of a _gaq object
531 */
532 function _setUpAnalytics() {
533
534 var gaUrl = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
535 var ss = doc.getElementsByTagName("script");
536 var googleAnalyticsLoaded = false;
537 for (var i = 0; i < ss.length; ++i) {
538
539 if (ss[i].src && ss[i].src.toLowerCase() == gaUrl.toLowerCase()) {
540
541 googleAnalyticsLoaded = true;
542 break;
543 }
544 }
545
546 if (!googleAnalyticsLoaded) {
547 var ga = doc.createElement("script");
548 ga.type = "text/javascript";
549 ga.async = true;
550 ga.src = gaUrl;
551 var s = document.getElementsByTagName("script")[0];
552 s.parentNode.insertBefore(ga, s);
553 }
554
555 var gaAccount = (cfg.debugLevel === 0) ? 'UA-16068464-16' : 'UA-16068464-17';
556
557 _ugaq.push(["unity._setDomainName", "none"]);
558 _ugaq.push(["unity._setAllowLinker", true]);
559 _ugaq.push(["unity._setReferrerOverride", ' '+this.location.toString()]);
560
561 _ugaq.push(["unity._setAccount", gaAccount]);
562 // $(GoogleRevisionPlaceholder)
563 }
564
565 /**
566 * sends analytics data to unity
567 * @private
568 */
569 function _sendUnityAnalytics(event, type, data, callback) {
570
571 if (!cfg.enableUnityAnalytics) {
572
573 if (callback) {
574
575 callback();
576 }
577
578 return;
579 }
580
581 var url = "http://unityanalyticscapture.appspot.com/event?u=" + encodeURIComponent(uid) + "&s=" + encodeURIComponent(seq) + "&e=" + encodeURIComponent(event);
582 // $(UnityRevisionPlaceholder)
583
584 if (cfg.referrer !== null) {
585
586 url += "?r=" + cfg.referrer;
587 }
588
589 if (type) {
590
591 url += "&t=" + encodeURIComponent(type);
592 }
593
594 if (data) {
595
596 url += "&d=" + encodeURIComponent(data);
597 }
598
599 var img = new Image();
600
601 if (callback) {
602
603 img.onload = img.onerror = callback;
604 }
605
606 img.src = url;
607 }
608
609 /**
610 * sends analytics data to google
611 * @private
612 */
613 function _sendGoogleAnalytics(event, type, data, callback) {
614
615 if (!cfg.enableGoogleAnalytics) {
616
617 if (callback) {
618
619 callback();
620 }
621
622 return;
623 }
624
625 var url = "/webplayer/install/" + event;
626 var join = "?";
627
628 if (type) {
629
630 url += join + "t=" + encodeURIComponent(type);
631 join = "&";
632 }
633
634 if (data) {
635
636 url += join + "d=" + encodeURIComponent(data);
637 join = "&";
638 }
639
640 if (callback) {
641
642 _ugaq.push(function () {
643 setTimeout(callback,1000);
644 //this.googleAnalyticsCallback = callback;
645 });
646 }
647
648 //try to shorten the URL to fit into customVariable
649 //it will try to replace the early directories to ..
650 var gameUrl = cfg.src;
651 if (gameUrl.length > 40) {
652 gameUrl = gameUrl.replace("http://","");
653 var paths = gameUrl.split("/");
654
655 var gameUrlFirst = paths.shift();
656 var gameUrlLast = paths.pop();
657 gameUrl = gameUrlFirst + "/../"+ gameUrlLast;
658
659 while(gameUrl.length < 40 && paths.length > 0) {
660 var nextpath = paths.pop();
661 if(gameUrl.length + nextpath.length + 5 < 40) {
662 gameUrlLast = nextpath + "/" + gameUrlLast;
663 } else {
664 gameUrlLast = "../" + gameUrlLast;
665 }
666 gameUrl = gameUrlFirst + "/../"+ gameUrlLast;
667 }
668 }
669 _ugaq.push(['unity._setCustomVar',
670 2, // This custom var is set to slot #1. Required parameter.
671 'GameURL', // The name acts as a kind of category for the user activity. Required parameter.
672 gameUrl, // This value of the custom variable. Required parameter.
673 3 // Sets the scope to page-level. Optional parameter.
674 ]);
675 _ugaq.push(['unity._setCustomVar',
676 1, // This custom var is set to slot #1. Required parameter.
677 'UnityObjectVersion', // The name acts as a kind of category for the user activity. Required parameter.
678 "2", // This value of the custom variable. Required parameter.
679 3 // Sets the scope to page-level. Optional parameter.
680 ]);
681 if (type) {
682 _ugaq.push(['unity._setCustomVar',
683 3, // This custom var is set to slot #1. Required parameter.
684 'installMethod', // The name acts as a kind of category for the user activity. Required parameter.
685 type, // This value of the custom variable. Required parameter.
686 3 // Sets the scope to page-level. Optional parameter.
687 ]);
688 }
689
690 _ugaq.push(["unity._trackPageview", url]);
691 }
692
693 return {
694 /**
695 * sends analytics data. optionally opens url once data has been sent
696 * @public
697 */
698 send : function (event, type, data, url) {
699
700 if (cfg.enableUnityAnalytics || cfg.enableGoogleAnalytics) {
701
702 debug('Analytics SEND', event, type, data, url);
703 }
704
705 ++seq;
706 var count = 2;
707
708 var callback = function () {
709
710 if (0 == --count) {
711
712 googleAnalyticsCallback = null;
713 window.location = url;
714 }
715 }
716
717 if (data === null || data === undefined) {
718 data = "";
719 }
720
721 _sendUnityAnalytics(event, type, data, url ? callback : null);
722 _sendGoogleAnalytics(event, type, data, url ? callback : null);
723 }
724 };
725 }();
726
727
728
729
730
731 /* Java Install - BEGIN */
732
733 /**
734 * @private
735 */
736 function _createObjectElement(attributes, params, elementToReplace) {
737
738 var i,
739 at,
740 pt,
741 ue,
742 pe;
743
744 if (ua.win && ua.ie) {
745
746 at = "";
747
748 for (i in attributes) {
749
750 at += ' ' + i + '="' + attributes[i] + '"';
751 }
752
753 pt = "";
754
755 for (i in params) {
756
757 pt += '<param name="' + i + '" value="' + params[i] + '" />';
758 }
759
760 elementToReplace.outerHTML = '<object' + at + '>' + pt + '</object>';
761
762 } else {
763
764 ue = doc.createElement("object");
765
766 for (i in attributes) {
767
768 ue.setAttribute(i, attributes[i]);
769 }
770
771 for (i in params) {
772
773 pe = doc.createElement("param");
774 pe.name = i;
775 pe.value = params[i];
776 ue.appendChild(pe);
777 }
778
779 elementToReplace.parentNode.replaceChild(ue, elementToReplace);
780 }
781 }
782
783 /**
784 * @private
785 */
786 function _checkImage(img) {
787
788 // img element not in the DOM yet
789 if (typeof img == "undefined") {
790
791 return false;
792 }
793
794 if (!img.complete) {
795
796 return false;
797 }
798
799 // some browsers always return true in img.complete, for those
800 // we can check naturalWidth
801 if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) {
802
803 return false;
804 }
805
806 // no other way of checking, assuming it is ok
807 return true;
808 }
809
810 /**
811 * @private
812 */
813 function _preloadJVMWhenReady(id) {
814
815 var needToWait = false;
816
817 for (var i = 0; i < imagesToWaitFor.length; i++) {
818 if (!imagesToWaitFor[i]) {
819 continue;
820 }
821 var img = doc.images[imagesToWaitFor[i]];
822 if (!_checkImage(img)) {
823 needToWait = true;
824 }
825 else {
826 imagesToWaitFor[i] = null;
827 }
828 }
829 if (needToWait) {
830 // check again in 100ms
831 setTimeout(arguments.callee, 100);
832 }
833 else {
834 // preload after a small delay, to make sure
835 // the images have actually rendered
836 setTimeout(function () {
837 _preloadJVM(id);
838 }, 100);
839 }
840 }
841
842
843 /**
844 * preloads the JVM and the Java Plug-in
845 * @private
846 */
847 function _preloadJVM(id) {
848
849 var re = doc.getElementById(id);
850
851 if (!re) {
852
853 re = doc.createElement("div");
854 var lastBodyElem = doc.body.lastChild;
855 doc.body.insertBefore(re, lastBodyElem.nextSibling);
856 }
857
858 var codebase = cfg.baseDownloadUrl + "3.0/jws/";
859
860 var a = {
861 id : id,
862 type : "application/x-java-applet",
863 code : "JVMPreloader",
864 width : 1,
865 height : 1,
866 name : "JVM Preloader"
867 };
868
869 var p = {
870 context : id,
871 codebase : codebase,
872 classloader_cache : false,
873 scriptable : true,
874 mayscript : true
875 };
876
877 _createObjectElement(a, p, re);
878 jQuery('#' + id).show();
879 //setVisibility(id, true);
880 }
881
882 /**
883 * launches java installer
884 * @private
885 */
886 function _doJavaInstall(id) {
887
888 triedJavaInstall = true;
889 _setSessionCookie(triedJavaCookie, triedJavaInstall);
890 var re = doc.getElementById(id);
891 var appletID = id + "_applet_" + instanceNumber;
892
893 applets[appletID] = {
894 attributes : cfg.attributes,
895 params : cfg.params,
896 callback : cfg.callback,
897 broken : cfg.broken
898 };
899
900 var applet = applets[appletID];
901
902 var a = {
903 id : appletID,
904 type : "application/x-java-applet",
905 archive : cfg.baseDownloadUrl + "3.0/jws/UnityWebPlayer.jar",
906 code : "UnityWebPlayer",
907 width : 1,
908 height : 1,
909 name : "Unity Web Player"
910 };
911
912 if (ua.win && ua.ff) {
913
914 a["style"] = "visibility: hidden;";
915 }
916
917 var p = {
918 context : appletID,
919 jnlp_href : cfg.baseDownloadUrl + "3.0/jws/UnityWebPlayer.jnlp",
920 classloader_cache : false,
921 installer : _getInstaller(),
922 image : baseDomain + "installation/unitylogo.png",
923 centerimage : true,
924 boxborder : false,
925 scriptable : true,
926 mayscript : true
927 };
928
929 for (var i in applet.params) {
930
931 if (i == "src") {
932
933 continue;
934 }
935
936 if (applet.params[i] != Object.prototype[i]) {
937
938 p[i] = applet.params[i];
939
940 if (i.toLowerCase() == "logoimage") {
941
942 p["image"] = applet.params[i];
943 }
944 else if (i.toLowerCase() == "backgroundcolor") {
945
946 p["boxbgcolor"] = "#" + applet.params[i];
947 }
948 else if (i.toLowerCase() == "bordercolor") {
949
950 // there's no way to specify border color
951 p["boxborder"] = true;
952 }
953 else if (i.toLowerCase() == "textcolor") {
954
955 p["boxfgcolor"] = "#" + applet.params[i];
956 }
957 }
958 }
959
960 // Create a dummy div element in the unityPlayer div
961 // so that it can be replaced with the 1x1 px applet.
962 // The applet will be resized when it has fully loaded,
963 // see appletStarted().
964 var divToBeReplacedWithApplet = doc.createElement("div");
965 re.appendChild(divToBeReplacedWithApplet);
966 _createObjectElement(a, p, divToBeReplacedWithApplet);
967 jQuery('#' + id).show();
968 //setVisibility(appletID, true);
969 }
970
971 /**
972 * @private
973 */
974 function _jvmPreloaded(id) {
975
976 // timeout prevents crash on ie
977 setTimeout(function () {
978
979 var re = doc.getElementById(id);
980
981 if (re) {
982 re.parentNode.removeChild(re);
983 }
984 }, 0);
985 }
986
987 /**
988 * @private
989 */
990 function _appletStarted(id) {
991 // set the size of the applet to the one from cloned attributes
992 var applet = applets[id],
993 appletElement = doc.getElementById(id),
994 childNode;
995
996 // the applet might have already finished by now
997 if (!appletElement) {
998
999 return;
1000 }
1001
1002 appletElement.width = applet.attributes["width"] || 600;
1003 appletElement.height = applet.attributes["height"] || 450;
1004
1005 // remove all the siblings of the applet
1006 var parentNode = appletElement.parentNode;
1007 var childNodeList = parentNode.childNodes;
1008
1009 for (var i = 0; i < childNodeList.length; i++) {
1010
1011 childNode = childNodeList[i];
1012 // Compare the child node with our applet element only if
1013 // it has the same type. Doing the comparison in other cases just
1014 // jumps out of the loop.
1015 if (childNode.nodeType == 1 && childNode != appletElement) {
1016
1017 parentNode.removeChild(childNode);
1018 }
1019 }
1020 }
1021
1022
1023 // java installation callback
1024 function _javaInstallDoneCallback(id, success, errormessage) {
1025
1026 debug('_javaInstallDoneCallback', id, success, errormessage);
1027 //console.log('javaInstallDoneCallback', id, success, errormessage);
1028
1029 if (!success) {
1030
1031 //var applet = applets[id];
1032 _setPluginStatus(kError, kJava, errormessage);
1033 //createMissingUnity(id, applet.attributes, applet.params, applet.callback, applet.broken, kJava, errormessage);
1034 }
1035 }
1036
1037 /* Java Install - END */
1038
1039
1040 /**
1041 * @private
1042 */
1043 function log() {
1044
1045 logHistory.push(arguments);
1046
1047 if ( cfg.debugLevel > 0 && window.console && window.console.log ) {
1048
1049 console.log(Array.prototype.slice.call(arguments));
1050 //console.log.apply(console, Array.prototype.slice.call(arguments));
1051 }
1052 }
1053
1054 /**
1055 * @private
1056 */
1057 function debug() {
1058
1059 logHistory.push(arguments);
1060
1061 if ( cfg.debugLevel > 1 && window.console && window.console.log ) {
1062
1063 console.log(Array.prototype.slice.call(arguments));
1064 //console.log.apply(console, Array.prototype.slice.call(arguments));
1065 }
1066 }
1067
1068 /**
1069 * appends px to the value if it's a plain number
1070 * @private
1071 */
1072 function _appendPX(value) {
1073
1074 if (/^[-+]?[0-9]+$/.test(value)) {
1075 value += "px";
1076 }
1077 return value;
1078 }
1079
1080 /**
1081 * detects unity web player.
1082 * @public
1083 * callback - accepts two parameters.
1084 * first one contains "installed", "missing", "broken" or "unsupported" value.
1085 * second one returns requested unity versions. plugin version is included as well.
1086 * versions - array of unity versions to detect.
1087 */
1088 function _detectUnityInternal (callback, versions) {
1089
1090 // console.debug('detectUnity this:', this);
1091 var self = this;
1092
1093 var status = kMissing;
1094 var data;
1095 nav.plugins.refresh();
1096
1097 if (ua.clientBrand === "??" || ua.clientPlatform === "???" || ua.mobile ) {
1098 status = kUnsupported;
1099 } else if (ua.op && ua.mac) { // Opera on MAC is unsupported
1100
1101 status = kUnsupported;
1102 data = "OPERA-MAC";
1103 } else if (
1104 typeof nav.plugins != "undefined"
1105 && nav.plugins[cfg.pluginName]
1106 && typeof nav.mimeTypes != "undefined"
1107 && nav.mimeTypes[cfg.pluginMimeType]
1108 && nav.mimeTypes[cfg.pluginMimeType].enabledPlugin
1109 ) {
1110
1111 status = kInstalled;
1112
1113 // make sure web player is compatible with 64-bit safari
1114 if (ua.sf && /Mac OS X 10_6/.test(nav.appVersion)) {
1115
1116 _getPluginVersion(function (version) {
1117
1118 if (!version || !version.plugin) {
1119
1120 status = kBroken;
1121 data = "OSX10.6-SFx64";
1122 }
1123
1124 callback(status, lastType, data, version);
1125 }, versions);
1126
1127 return;
1128 } else if (ua.mac && ua.ch) { // older versions have issues on chrome
1129
1130 _getPluginVersion(function (version) {
1131
1132 if (version && (_getNumericUnityVersion(version.plugin) <= _getNumericUnityVersion("2.6.1f3"))) {
1133 status = kBroken;
1134 data = "OSX-CH-U<=2.6.1f3";
1135 }
1136
1137 callback(status, lastType, data, version);
1138 }, versions);
1139
1140 return;
1141 } else if (versions) {
1142
1143 _getPluginVersion(function (version) {
1144 callback(status, lastType, data, version);
1145 }, versions);
1146 return;
1147 }
1148 } else if (ua.ie) {
1149 var activeXSupported = false;
1150 try {
1151 if (ActiveXObject.prototype != null) {
1152 activeXSupported = true;
1153 }
1154 } catch(e) {}
1155
1156 if (!activeXSupported) {
1157 status = kUnsupported;
1158 data = "ActiveXFailed";
1159 } else {
1160 status = kMissing;
1161 try {
1162 var uo = new ActiveXObject("UnityWebPlayer.UnityWebPlayer.1");
1163 var pv = uo.GetPluginVersion();
1164
1165 if (versions) {
1166 var v = {};
1167 for (var i = 0; i < versions.length; ++i) {
1168 v[versions[i]] = uo.GetUnityVersion(versions[i]);
1169 }
1170 v.plugin = pv;
1171 }
1172
1173 status = kInstalled;
1174 // 2.5.0 auto update has issues on vista and later
1175 if (pv == "2.5.0f5") {
1176 var m = /Windows NT \d+\.\d+/.exec(nav.userAgent);
1177 if (m && m.length > 0) {
1178 var wv = parseFloat(m[0].split(' ')[2]);
1179 if (wv >= 6) {
1180 status = kBroken;
1181 data = "WIN-U2.5.0f5";
1182 }
1183 }
1184 }
1185 } catch(e) {}
1186 }
1187 }
1188 callback(status, lastType, data, v);
1189 }
1190
1191 /**
1192 * Detects unity web player. But doesn't modify the current UnityObject instance, and doesn't send analytics.
1193 * @public
1194 * callback - accepts two parameters.
1195 * first one contains "installed", "missing", "broken" or "unsupported" value.
1196 * second one returns requested unity versions. plugin version is included as well.
1197 * versions - array of unity versions to detect.
1198 */
1199 function _detectUnityNoAnalytics (callback, versions) {
1200 _detectUnityInternal(function(status, lastType, data, v){
1201 callback(status, v);
1202 }, versions);
1203 }
1204
1205 /**
1206 * Detects unity web player. Also modify the current UnityObject instance, and sends analytics.
1207 * @public
1208 * callback - accepts two parameters.
1209 * first one contains "installed", "missing", "broken" or "unsupported" value.
1210 * second one returns requested unity versions. plugin version is included as well.
1211 * versions - array of unity versions to detect.
1212 */
1213 function _detectUnityWithAnalytics (callback, versions) {
1214 _detectUnityInternal(function(status, lastType, data, v){
1215 _setPluginStatus(status, lastType, data);
1216 callback(status, v);
1217 }, versions);
1218 }
1219
1220
1221 var publicAPI = /** @lends UnityObject2.prototype */ {
1222
1223 /**
1224 * Get Debug Level (0=Disabled)
1225 * @public
1226 * @return {Number} Debug Level
1227 */
1228 getLogHistory: function () {
1229
1230 return logHistory; // JSON.stringify()
1231 },
1232
1233
1234 /**
1235 * Get configuration object
1236 * @public
1237 * @return {Object} cfg
1238 */
1239 getConfig: function () {
1240
1241 return cfg; // JSON.stringify()
1242 },
1243
1244
1245 /**
1246 * @public
1247 * @return {Object} detailed info about OS and Browser.
1248 */
1249 getPlatformInfo: function () {
1250
1251 return ua;
1252 },
1253
1254
1255 /**
1256 * Initialize plugin config and proceed with attempting to start the webplayer.
1257 * @public
1258 */
1259 initPlugin: function (targetEl, src) {
1260
1261 cfg.targetEl = targetEl;
1262 cfg.src = src;
1263
1264 debug('ua:', ua);
1265 //console.debug('initPlugin this:', this);
1266 //_detectUnityWithAnalytics(this.handlePluginStatus);
1267 var self = this;
1268 _detectUnityWithAnalytics(function(status, v){
1269 self.handlePluginStatus(status, v);
1270 });
1271 },
1272
1273
1274 /**
1275 * detects unity web player.
1276 * @public
1277 * callback - accepts two parameters.
1278 * first one contains "installed", "missing", "broken" or "unsupported" value.
1279 * second one returns requested unity versions. plugin version is included as well.
1280 * versions - optional array of unity versions to detect.
1281 */
1282 detectUnity: function (callback, versions) {
1283 var self = this;
1284 _detectUnityNoAnalytics(function(status, v){
1285 callback.call(self, status, v);
1286 }, versions);
1287 },
1288
1289
1290
1291 /**
1292 * @public
1293 * @return {Object} with info about Unity WebPlayer plugin status (not installed, loading, running etc..)
1294 */
1295 handlePluginStatus: function (status, versions) {
1296
1297 // Store targetEl in the closure, to be able to get it back if setTimeout calls again.
1298 var targetEl = cfg.targetEl;
1299
1300 var $targetEl = jQuery(targetEl);
1301
1302 switch(status) {
1303
1304 case kInstalled:
1305
1306 // @todo add support for alternate custom handlers.
1307 this.notifyProgress($targetEl);
1308 this.embedPlugin($targetEl, cfg.callback);
1309 break;
1310
1311 case kMissing:
1312
1313 this.notifyProgress($targetEl);
1314 //this.installPlugin($targetEl);
1315
1316 var self = this;
1317 var delayTime = (cfg.debugLevel === 0) ? 1000 : 8000;
1318
1319 // Do a delay and re-check for plugin
1320 setTimeout(function () {
1321
1322 cfg.targetEl = targetEl;
1323 self.detectUnity(self.handlePluginStatus);
1324 }, delayTime);
1325
1326 break;
1327
1328 case kBroken:
1329 // Browser needs to restart after install
1330 this.notifyProgress($targetEl);
1331 break;
1332
1333 case kUnsupported:
1334
1335 this.notifyProgress($targetEl);
1336 break;
1337 }
1338
1339 },
1340
1341 /**
1342 * @public
1343 * @return {Object} with detailed plugin info, version number and other info that can be retrieved from the plugin.
1344 */
1345 /*getPluginInfo: function () {
1346
1347 },*/
1348
1349 /**
1350 * @public
1351 */
1352 getPluginURL: function () {
1353
1354 var url = "http://unity3d.com/webplayer/";
1355
1356 if (ua.win) {
1357
1358 url = cfg.baseDownloadUrl + _getWinInstall();
1359
1360 } else if (nav.platform == "MacIntel") {
1361
1362 url = cfg.baseDownloadUrl + (cfg.fullInstall ? "webplayer-i386.dmg" : "webplayer-mini.dmg");
1363
1364 if (cfg.referrer !== null) {
1365
1366 url += "?referrer=" + cfg.referrer;
1367 }
1368
1369 } else if (nav.platform == "MacPPC") {
1370
1371 url = cfg.baseDownloadUrl + (cfg.fullInstall ? "webplayer-ppc.dmg" : "webplayer-mini.dmg");
1372
1373 if (cfg.referrer !== null) {
1374
1375 url += "?referrer=" + cfg.referrer;
1376 }
1377 }
1378
1379 return url;
1380 },
1381
1382 /**
1383 * @public
1384 */
1385 getClickOnceURL: function () {
1386
1387 return cfg.baseDownloadUrl + "3.0/co/UnityWebPlayer.application?installer=" + encodeURIComponent(cfg.baseDownloadUrl + _getWinInstall());
1388 },
1389
1390 /**
1391 * Embed the plugin into the DOM.
1392 * @public
1393 */
1394 embedPlugin: function (targetEl, callback) {
1395
1396 targetEl = jQuery(targetEl).empty();
1397
1398 var src = cfg.src; //targetEl.data('src'),
1399 var width = cfg.width || "100%"; //TODO: extract those hardcoded values
1400 var height = cfg.height || "100%";
1401 var self = this;
1402
1403 if (ua.win && ua.ie) {
1404 // ie, dom and object element do not mix & match
1405
1406 var at = "";
1407
1408 for (var i in cfg.attributes) {
1409 if (cfg.attributes[i] != Object.prototype[i]) {
1410 if (i.toLowerCase() == "styleclass") {
1411 at += ' class="' + cfg.attributes[i] + '"';
1412 }
1413 else if (i.toLowerCase() != "classid") {
1414 at += ' ' + i + '="' + cfg.attributes[i] + '"';
1415 }
1416 }
1417 }
1418
1419 var pt = "";
1420
1421 // we manually add SRC here, because its now defined on the target element.
1422 pt += '<param name="src" value="' + src + '" />';
1423 pt += '<param name="firstFrameCallback" value="UnityObject2.instances[' + instanceNumber + '].firstFrameCallback();" />';
1424
1425 for (var i in cfg.params) {
1426
1427 if (cfg.params[i] != Object.prototype[i]) {
1428
1429 if (i.toLowerCase() != "classid") {
1430
1431 pt += '<param name="' + i + '" value="' + cfg.params[i] + '" />';
1432 }
1433 }
1434 }
1435
1436 //var tmpHtml = '<div id="' + targetEl.attr('id') + '" style="width: ' + _appendPX(width) + '; height: ' + _appendPX(height) + ';"><object classid="clsid:444785F1-DE89-4295-863A-D46C3A781394" style="display: block; width: 100%; height: 100%;"' + at + '>' + pt + '</object></div>';
1437 var tmpHtml = '<object classid="clsid:444785F1-DE89-4295-863A-D46C3A781394" style="display: block; width: ' + _appendPX(width) + '; height: ' + _appendPX(height) + ';"' + at + '>' + pt + '</object>';
1438 var $object = jQuery(tmpHtml);
1439 targetEl.append( $object );
1440 embeddedObjects.push( targetEl.attr('id') );
1441 unityObject = $object[0];
1442
1443 } else {
1444
1445 // Create and append embed element into DOM.
1446 var $embed = jQuery('<embed/>')
1447 .attr({
1448 src: src,
1449 type: cfg.pluginMimeType,
1450 width: width,
1451 height: height,
1452 firstFrameCallback: 'UnityObject2.instances[' + instanceNumber + '].firstFrameCallback();'
1453 })
1454 .attr(cfg.attributes)
1455 .attr(cfg.params)
1456 .css({
1457 display: 'block',
1458 width: _appendPX(width),
1459 height: _appendPX(height)
1460 })
1461 .appendTo( targetEl );
1462 unityObject = $embed[0];
1463 }
1464
1465 //Auto focus the new object/embed, so players dont have to click it before using it.
1466 //setTimeout is here to workaround a chrome bug.
1467 //we should not invoke focus on safari on mac. it causes some Input bugs.
1468 if (!ua.sf || !ua.mac) {
1469 setTimeout(function() {
1470 unityObject.focus();
1471 }, 100);
1472 }
1473
1474 if (callback) {
1475
1476 callback();
1477 }
1478 },
1479
1480 /**
1481 * Determine which installation method to use on the current platform, and return an array with their identifiers (i.e. 'ClickOnceIE', 'JavaInstall', 'Manual')
1482 * Take into account which previous methods might have been attempted (and failed) and skip to next best method.
1483 * @public
1484 * @return {String}
1485 */
1486 getBestInstallMethod: function () {
1487
1488 // Always fall back to good old manual (download) install.
1489 var method = 'Manual';
1490
1491 //We only have manual install for 64bit plugin so far.
1492 if (ua.x64)
1493 return method;
1494
1495 // Is Java available and not yet attempted?
1496 if (cfg.enableJava && ua.java && triedJavaInstall === false) {
1497
1498 method = 'JavaInstall';
1499 }
1500 // Is ClickOnce available and not yet attempted?
1501 else if (cfg.enableClickOnce && ua.co && triedClickOnce === false) {
1502
1503 method = 'ClickOnceIE';
1504 }
1505
1506 return method;
1507 },
1508
1509 /**
1510 * Tries to install the plugin using the specified method.
1511 * If no method is passed, it will try to use this.getBestInstallMethod()
1512 * @public
1513 * @param {String} method The desired install method
1514 */
1515 installPlugin: function(method) {
1516 if (method == null || method == undefined) {
1517 method = this.getBestInstallMethod();
1518 }
1519
1520 var urlToOpen = null;
1521 switch(method) {
1522
1523 case "JavaInstall":
1524 this.doJavaInstall(cfg.targetEl.id);
1525 break;
1526 case "ClickOnceIE":
1527 triedClickOnce = true;
1528 _setSessionCookie(triedClickOnceCookie, triedClickOnce);
1529 var $iframe = jQuery("<iframe src='" + this.getClickOnceURL() + "' style='display:none;' />");
1530 jQuery(cfg.targetEl).append($iframe);
1531 break;
1532 default:
1533 case "Manual":
1534 //doc.location = this.getPluginURL();
1535 //urlToOpen = this.getPluginURL();
1536 var $iframe = jQuery("<iframe src='" + this.getPluginURL() + "' style='display:none;' />");
1537 jQuery(cfg.targetEl).append($iframe);
1538 break;
1539 }
1540
1541 lastType = method;
1542 _an.send(kStart, method, null, null);
1543
1544 },
1545
1546 /**
1547 * Trigger event using jQuery(document).trigger()
1548 * @public
1549 */
1550 //TODO: verify its use.
1551 trigger: function (event, params) {
1552
1553 if (params) {
1554
1555 debug('trigger("' + event + '")', params);
1556
1557 } else {
1558
1559 debug('trigger("' + event + '")');
1560 }
1561
1562 jQuery(document).trigger(event, params);
1563 },
1564
1565 /**
1566 * Notify observers about onProgress event
1567 * @public
1568 */
1569 notifyProgress: function (targetEl) {
1570
1571 //debug('*** notifyProgress ***')
1572
1573 if (typeof progressCallback !== "undefined" && typeof progressCallback === "function") {
1574
1575 var payload = {
1576
1577 ua: ua,
1578 pluginStatus: pluginStatus,
1579 bestMethod: null,
1580 lastType: lastType,
1581 targetEl: cfg.targetEl,
1582 unityObj: this
1583 };
1584
1585 if (pluginStatus === kMissing) {
1586
1587 payload.bestMethod = this.getBestInstallMethod();
1588 }
1589
1590 if (latestStatus !== pluginStatus) { //Execute only on state change
1591 latestStatus = pluginStatus;
1592
1593 progressCallback(payload);
1594 }
1595 }
1596 },
1597
1598 /**
1599 * Subscribe to onProgress notification
1600 * @public
1601 */
1602 observeProgress: function (callback) {
1603
1604 progressCallback = callback;
1605 },
1606
1607
1608 /**
1609 * Callback made by the WebPlayer plugin when the first frame is rendered.
1610 * @public
1611 */
1612 firstFrameCallback : function () {
1613
1614 debug('*** firstFrameCallback (' + instanceNumber + ') ***');
1615 pluginStatus = kFirst;
1616 this.notifyProgress();
1617
1618 /*
1619 // What?
1620 if (status == kFirst) {
1621 if (pluginStatus == null) {
1622 return;
1623 }
1624 }
1625 */
1626
1627 //Webplayer was already installed.
1628 //Should only log firstframes if it happened after a install.
1629 if (wasMissing === true) {
1630 _an.send(pluginStatus, lastType);
1631 }
1632
1633 //setRunStatus(kFirst, lastType);
1634 },
1635
1636 /**
1637 * Get a string from a session cookie or SessionStorage
1638 * @public
1639 * @return {String}
1640 */
1641 /*getSessionString: function (key) {
1642
1643 },*/
1644
1645 /**
1646 * Set a string via a session cookie or SessionStorage
1647 * @public
1648 */
1649 /* setSessionString: function (key, value) {
1650
1651 },*/
1652
1653 /**
1654 * Get a string from a persistent cookie
1655 * @public
1656 * @return {String}
1657 */
1658 /*getCookie: function (key) {
1659
1660 },*/
1661
1662 /**
1663 * Set a string to a persistent cookie
1664 * @public
1665 */
1666 /*setCookie: function (key, value, expiryDate) {
1667
1668 },*/
1669
1670 /**
1671 * Exposed private function
1672 * @public
1673 */
1674 setPluginStatus: function (status, type, data, url) {
1675
1676 _setPluginStatus(status, type, data, url);
1677 },
1678
1679 /**
1680 * Exposed private function
1681 * @public
1682 */
1683 doJavaInstall : function (id) {
1684
1685 _doJavaInstall(id);
1686 },
1687
1688 /**
1689 * Exposed private function
1690 * @public
1691 */
1692 jvmPreloaded : function (id) {
1693
1694 _jvmPreloaded(id);
1695 },
1696
1697 /**
1698 * Exposed private function
1699 * @public
1700 */
1701 appletStarted : function (id) {
1702
1703 _appletStarted(id);
1704 },
1705
1706 /**
1707 * Exposed private function
1708 * @public
1709 */
1710 javaInstallDoneCallback : function (id, success, errormessage) {
1711
1712 _javaInstallDoneCallback(id, success, errormessage);
1713 },
1714
1715 getUnity: function() {
1716 return unityObject;
1717 }
1718 }
1719
1720 // Internal store of each instance.
1721 instanceNumber = UnityObject2.instances.length;
1722 UnityObject2.instances.push(publicAPI);
1723
1724 return publicAPI;
1725
1726 };
1727
1728 /**
1729 * @static
1730 **/
1731 UnityObject2.instances = [];